/* //device/system/broncho-ril/reference-ril.c
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include <telephony/ril.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <alloca.h>
#include "atchannel.h"
#include "at_tok.h"
#include "ril_util.h"
#include <getopt.h>
#include "broncho-ril.h"

#define LOG_TAG "RIL"
#include "broncho_log.h"

typedef struct _StkContext
{
	char* 	cur_proactive_cmd;
}StkContext;

static void onUnsolicited_stkpci(RIL* thiz, const char* s);

static StkContext* stkGetContext(RIL* thiz)
{
	StkContext* ret = RIL_GetPrivInfo(thiz, "stk_ctx");

	if(ret == NULL)
	{
		ret = calloc(1, sizeof(StkContext));
		RIL_SetPrivInfo(thiz, ret, "stk_ctx");
	}

	return ret;
}

static void requestStkSendEnvelopeCommand(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	char* envelop_cmd = (char*)data;
	char* cmd = NULL;

	asprintf(&cmd, "AT+STKENV=\"%s\"", envelop_cmd);
	if(ril_command_exec_for_result(thiz, cmd))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
	    RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	free(cmd);

	return;	
}

static void requestStkSendSms(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	if(ril_command_exec_full_for_result(thiz, "AT+STKSMS", 60000))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	
	return;
}

static void requestStkSendDtmf(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	if(ril_command_exec_full_for_result(thiz, "AT+STKDTMF", 5000))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	
	return;
}
static void requestStkSendSs(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	if(ril_command_exec_full_for_result(thiz, "AT+STKSS", 25000))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	
	return;
}
static void requestStkSendUssd(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	if(ril_command_exec_full_for_result(thiz, "AT+STKUSSD", 25000))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	
	return;
}
static void requestStkSetupCall(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	int   accept = ((int*)data)[0];

	if((accept == 0) || ril_command_exec_full_for_result(thiz, "AT+STKCALL", 25000))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	
	return;
}

static void requestStkGetLastProactiveCommand(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	StkContext* ctx = stkGetContext(thiz);

	RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	if(ctx->cur_proactive_cmd != NULL)
	{
		onUnsolicited_stkpci(thiz, ctx->cur_proactive_cmd);
	}

	return;
}

static void requestStkSendTerminalResponse(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	char* response = (char*)data;
	char* cmd = NULL;

	asprintf(&cmd, "AT+STKTR=\"%s\"", response);
	if(ril_command_exec_for_result(thiz, cmd))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
	    RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	free(cmd);

	return;	
}

static void onUnsolicited_StkTrind(RIL* thiz, const char* s)
{
	char* dump_s = NULL;
	char* line = NULL;
	int result[1] = {0};

	dump_s = strdup (s);
	line = dump_s;
	at_line_scanf_int(line, result);
	free(dump_s);
	RIL_onUnsolicitedResponse(thiz, RIL_UNSOL_STK_RESULT, result, sizeof(result));

	return;
}

static void onUnsolicited_stkpci(RIL* thiz, const char* s)
{
	char* response = NULL;
	char* line = NULL;
	char* dump_s = NULL;
	int type = 0;
	int err = 0;

	dump_s = strdup(s);
	line = dump_s;
	do
	{
		at_tok_start(&line);
		if((err = at_tok_nextint(&line, &type)) < 0)
		{
			break;
		}

		if(type == 2)
		{
			RIL_onUnsolicitedResponse(thiz, RIL_UNSOL_STK_SESSION_END, NULL, 0);
		}
		else
		{
			err = at_tok_nextstr(&line, &response);
			if(err == 0)
			{
				RIL_onUnsolicitedResponse(thiz, RIL_UNSOL_STK_PROACTIVE_COMMAND, response, sizeof(char*));
			}
		}
	}while(0);

	free(dump_s);

	return;
}

int RIL_initialize_stk (RIL* thiz)
{
	return 1;
}

int RIL_onUnsolicited_stk (RIL* thiz, const char* s)
{
	int ret = 0;

	if(strStartsWith(s, "+STKPCI:"))
	{
		StkContext* ctx = stkGetContext(thiz);

		onUnsolicited_stkpci(thiz, s);
		if(ctx->cur_proactive_cmd != NULL)
		{
			free(ctx->cur_proactive_cmd);
		}
		ctx->cur_proactive_cmd = strdup(s);
		ret = 1;
	}
	else if(strStartsWith(s, "+STKTRIND:"))
	{
		onUnsolicited_StkTrind(thiz, s);
		ret = 1;
	}

	return ret;
}

int RIL_onRequest_stk (RIL* thiz, int request, void *data, size_t datalen, RIL_Token t)
{
	switch (request)
	{
	case RIL_REQUEST_STK_GET_PROFILE:
	case RIL_REQUEST_STK_SET_PROFILE:
		RIL_onRequestComplete(thiz, t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
		break;

	case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
		requestStkSendEnvelopeCommand(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
		requestStkSendTerminalResponse(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
		requestStkGetLastProactiveCommand(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
		requestStkSetupCall(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_SEND_SMS:
		requestStkSendSms(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_SEND_DTMF:
		requestStkSendDtmf(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_SEND_USSD:
		requestStkSendUssd(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_STK_SEND_SS:
		requestStkSendSs(thiz, data, datalen, t);
		break;

	default:
		RIL_onRequestComplete(thiz, t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
		break;

	}
	return 1;
}

